//
// Created by gogoqiu on 2022/3/7.
//

#include <stdio.h>
//#include <libavutil/time.h>

#define __STDC_CONSTANT_MACROS

#ifdef _WIN32
//Windows
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
#include "SDL/SDL.h"
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavutil/time.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavdevice/avdevice.h>
#include <SDL2/SDL.h>
/*
#include <X11/Xlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/extensions/XShm.h>
*/
#ifdef __cplusplus
};
#endif
#endif

//Output YUV420P
#define OUTPUT_YUV420P 0
//'1' Use Dshow
//'0' Use VFW
#define USE_DSHOW 0


//Refresh Event
#define SFM_REFRESH_EVENT  (SDL_USEREVENT + 1)

#define SFM_BREAK_EVENT  (SDL_USEREVENT + 2)
#define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22)
#define CODEC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER

int thread_exit=0;

//Output FFmpeg's av_log()
void custom_log(void *ptr, int level, const char *fmt, va_list vl) {
    FILE *fp = fopen("/tmp/av_log.txt", "a+");
    if (fp) {
        vfprintf(fp, fmt, vl);
        fflush(fp);
        fclose(fp);
    }
}

int main(int argc, char* argv[]) {
    AVFormatContext *pFormatCtx;
    int i, videoStreamIndex;
    //render codec context
    AVCodecContext *pDeviceVideoCodecCtx;
    AVCodec *pCodec;

    //av_log_set_callback(custom_log);
    av_register_all();
    avformat_network_init();
    avdevice_register_all();

    //
    pFormatCtx = avformat_alloc_context();

    //AVCodec *  pH264Codec = avcodec_find_encoder_by_name("h264_qsv");
    AVCodec *pH264Codec = avcodec_find_encoder_by_name("h264_vaapi");
    //AVCodec *  pH264Codec = avcodec_find_encoder_by_name("libx264");
    //AVCodec *  pH264Codec = avcodec_find_encoder(AV_CODEC_ID_H264);
    if (nullptr == pH264Codec) {
        printf("%s", "avcodec_find_encoder failed");
        return -1;
    }

    AVCodec *pc = avcodec_find_encoder(AV_CODEC_ID_H264);
    pc = avcodec_find_encoder_by_name("h264_vaapi");
    //pc = avcodec_find_encoder_by_name("h264_v4l2m2m");
    if (!pc) {
        //goto close_muxer;
        return -1;
    }
    // "/dev/dri/renderD128"

    AVCodecContext * pcc = avcodec_alloc_context3(pc);
    pcc->pix_fmt = pc->pix_fmts[0];
    //pcc->pix_fmt = AV_PIX_FMT_YUV420P;
    pcc->codec_id = pc->id;
    pcc->codec_type = pc->type;
    pcc->time_base.num = 1;
    pcc->time_base.den = 1;
    pcc->width = 640;
    pcc->height = 480;

    AVDictionary *opts = nullptr;
    //av_dict_set(&opts, "b", "2.5M", AV_DICT_MATCH_CASE );
    av_dict_set(&opts, "b", "2.5M", 0 );
    av_dict_set(&opts, "vaapi_device", "/dev/dri/renderD128", 0 );
    av_dict_set(&opts, "hwaccel", "vaapi", 0 );
    av_dict_set(&opts, "hwaccel_output_format", "vaapi", 0 );

    int ok = avcodec_open2(pcc, pc, &opts );
    if (ok != 0) {
        //goto free_encoder;
        return -1;
    }
    printf("ok!");
    return 0;
}
